import json

from rest_framework import generics, permissions, filters, status, viewsets, serializers
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied
from rest_framework.generics import get_object_or_404
from rest_framework.pagination import PageNumberPagination
from rest_framework.parsers import MultiPartParser, FormParser
from django_filters.rest_framework import DjangoFilterBackend
from .models import Note, Comment, Like, Category, Tag
from .serializers import NoteSerializer, CommentSerializer, LikeSerializer, NoteDataSerializer, CategorySerializer, \
    TagSerializer
from rest_framework.response import Response

from rest_framework.permissions import BasePermission, IsAuthenticatedOrReadOnly, IsAuthenticated


class IsOwnerOrPublic(BasePermission):
    def has_object_permission(self, request, view, obj):
        # 公开的笔记可以被任何人查看
        if obj.privacy == 'public':
            return True
        # 半公开笔记只能被关注的用户查看
        if obj.privacy == 'protected' and request.user in obj.user.followers.all():
            return True
        # 私密笔记只能由笔记拥有者查看
        return obj.user == request.user



class NotePagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'pageSize'
    max_page_size = 100


class NoteListCreateView(generics.ListCreateAPIView):
    queryset = Note.objects.all()
    serializer_class = NoteSerializer
    permission_classes = [permissions.AllowAny]  # 查询笔记无需登录
    pagination_class = NotePagination
    parser_classes = [MultiPartParser, FormParser]  # 支持上传文件
    filterset_fields = ['category', 'privacy']  # 支持按分类和隐私级别过滤
    search_fields = ['title', 'content', 'tags__name']  # 支持搜索的字段
    filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend]  # 添加搜索和过滤后端

    def perform_create(self, serializer):
        # 检查用户是否已登录
        if self.request.user.is_authenticated:
            tags_str = self.request.data.get('tags', '[]')
            try:
                tags = json.loads(tags_str)  # 将 JSON 字符串解析为列表
            except json.JSONDecodeError:
                tags = []

            # 保存笔记并关联用户和标签
            serializer.save(user=self.request.user, tags=tags)
        else:
            # 如果未登录，返回 403 禁止访问
            return Response({"detail": "Authentication required to create a note."}, status=status.HTTP_403_FORBIDDEN)


    def get_queryset(self):
        """
        过滤、搜索等条件会通过过滤器自动应用在查询集中
        """
        # 返回当前用户的笔记或者全部公开的笔记
        queryset = Note.objects.all().only('id', 'title', 'user', 'cover_image', 'summary')

        # 例如，返回当前登录用户的笔记（如果需要实现类似功能）
        # if self.request.user.is_authenticated:
        #     queryset = queryset.filter(user=self.request.user)

        return queryset


class NoteDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Note.objects.all()
    serializer_class = NoteDataSerializer
    permission_classes = [permissions.AllowAny]


    def get_queryset(self):
        return Note.objects.all()


class CommentViewSet(viewsets.ModelViewSet):
    serializer_class = CommentSerializer
    permission_classes = [permissions.AllowAny]


    def get_queryset(self):
        """
            重写此方法以获取与特定笔记相关的评论。
            """
        note_id = self.request.query_params.get('note_id')
        if note_id:
            return Comment.objects.filter(note_id=note_id)
        return Comment.objects.none()  # 如果没有传入 note_id，则不返回任何评论

    def perform_create(self, serializer):
        # 从请求中获取 note_id 并将其传递给 serializer.save()
        note_id = self.request.data.get('note_id')
        if not note_id:
            raise serializers.ValidationError("note_id is required")

        # 获取关联的 Note 对象
        try:
            note = Note.objects.get(id=note_id)
        except Note.DoesNotExist:
            raise serializers.ValidationError("Note not found")

        # 将 note 和 user 传递给 serializer
        serializer.save(user=self.request.user, note=note)

    @action(detail=True, methods=['POST'])
    def like(self, request, pk=None):
        comment = self.get_object()
        comment.likes += 1
        comment.save()
        return Response({'status': 'comment liked', 'likes': comment.likes})

    @action(detail=True, methods=['GET'])
    def replies(self, request, pk=None):
        comment = self.get_object()
        replies = comment.replies.all()
        serializer = CommentSerializer(replies, many=True)
        return Response(serializer.data)

class LikeToggleView(generics.GenericAPIView):
    serializer_class = LikeSerializer
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, *args, **kwargs):
        note_id = self.kwargs.get('note_id')
        note = Note.objects.get(id=note_id)
        user = request.user

        # 尝试获取现有的点赞对象
        like, created = Like.objects.get_or_create(user=user, note=note)

        if created:
            # 如果 `created` 为 True，则表示用户刚刚点赞
            serializer = self.get_serializer(like)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            # 如果用户已经点赞，则取消点赞（删除 `Like` 对象）
            like.delete()
            return Response({'detail': 'Like removed'}, status=status.HTTP_204_NO_CONTENT)


class CategoryListCreateView(generics.ListCreateAPIView):
    serializer_class = CategorySerializer
    permission_classes = [permissions.AllowAny]

    def get_queryset(self):
        return Category.objects.all()

    # def perform_create(self, serializer):
    #     note = Note.objects.get(id=self.kwargs['note_id'])
    #     serializer.save(user=self.request.user, note=note)


class TagListCreateView(generics.ListCreateAPIView):
    queryset = Tag.objects.all()
    serializer_class = TagSerializer
    permission_classes = [IsAuthenticatedOrReadOnly]

    # 禁用分页，直接返回所有结果
    def get_queryset(self):
        return Tag.objects.all()

    # 重写 list 方法，禁用分页的返回
    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset()
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)